<template>
  <a-upload
    name="file"
    action="#"
    v-model:file-list="fileList"
    :before-upload="beforeUpload"
    :custom-request="upload"
    :maxCount="1"
    :multiple="false"
    :show-upload-list="true"
    @remove="reset"
    @change="handleChange"
  >
    <div v-if="fileList.length < 1">
      <a-button>
        <UploadOutlined></UploadOutlined>
        上传
      </a-button>
    </div>

    <template #itemRender="{ file, actions }">
      <a-progress :percent="percentage" :status="status" v-if="progressVisible" />
      <div>
        <LinkOutlined />
        {{ file.name }} {{ `${formatFileSize(file.size)}MB` }}
        <a href="javascript:" @click="actions.remove">
          <DeleteOutlined />
        </a>
      </div>
    </template>
  </a-upload>
</template>

<script>
import { PlusOutlined, UploadOutlined, LinkOutlined, DeleteOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import { getData } from '@/services';
import { formatFileSize } from '@/utils';
import COS from 'cos-js-sdk-v5';

export default {
  components: {
    PlusOutlined,
    UploadOutlined,
    LinkOutlined,
    DeleteOutlined,
  },
  props: {
    modelValue: {
      type: String,
      default: () => '',
    },
    batchNumber: {
      type: String,
      required: true,
    },
    bondType: {
      type: String,
      required: true,
    },
    fileType: {
      type: String,
      required: true,
    },
  },
  data() {
    return {
      fileList: [],
      cosFileData: {
        key: null,
        fileTemporaryUrl: null,
      },
      progressVisible: false,
      percentage: 0,
      status: 'success',
    };
  },
  watch: {
    fileList: {
      handler(newVal) {
        if (newVal.length > 0) {
          const key = newVal[0].key;
          if (key) this.$emit('update:modelValue', key);
        } else {
          this.$emit('update:modelValue', null);
        }
      },
      deep: true,
    },
  },
  methods: {
    formatFileSize,
    async beforeUpload(file) {
      const maxSize = 12 * 1024 * 1024; // 12MB
      if (file.size > maxSize) {
        message.error('附件大小超过12MB');
        this.fileList = [];
        return false;
      }
      const { type } = file;
      // todo: 可以在这里添加文件类型检查
      return true;
    },
    async upload(file) {
      const res = await getData(`/api/auth/cos/getKeyAndCredentials`);
      const { tmpSecretId, tmpSecretKey, sessionToken, startTime, expiredTime, bucket, region } =
        res.data;

      const cos = new COS({
        getAuthorization: async function (options, callback) {
          callback({
            TmpSecretId: tmpSecretId,
            TmpSecretKey: tmpSecretKey,
            SecurityToken: sessionToken,
            StartTime: startTime,
            ExpiredTime: expiredTime,
            ScopeLimit: true,
          });
        },
      });

      this.progressVisible = true;
      this.status = 'active';
      const folderPath = `${this.bondType}-${this.fileType}/`;
      const fileName = `${this.batchNumber}-${new Date().getTime()}-${file.file.name}`;
      const key = `${folderPath}${fileName}`;

      const that = this;

      // 上传文件
      cos.uploadFile(
        {
          Bucket: bucket,
          Region: region,
          Key: key,
          Body: file.file,
          onProgress: function (progressEvent) {
            if (progressEvent.lengthComputable) {
              that.percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            }
          },
        },
        function (err, data) {
          that.status = 'success';
          that.progressVisible = false;
          that.fileList = [
            {
              uid: '-1',
              name: file.file.name,
              status: 'done',
              key: key,
              size: file.file.size,
            },
          ];

          that.$emit('change');
          that.$emit('size-changed', file.file.size);
        },
      );
    },

    reset() {
      if (!this.fileList.length) return;
      const size = this.fileList[0].size;
      this.fileList = [];
      this.progressVisible = false;
      this.percentage = 0;
      this.status = 'success';
      this.$emit('update:modelValue', null);
      this.$emit('size-changed', -size);
    },
    handleChange(info) {
      if (info.file.status === 'done') {
      } else if (info.file.status === 'error') {
      } else {
        this.fileList = [];
      }
    },
  },
};
</script>

<style lang="less" scoped>
.ant-upload-select-picture-card i {
  font-size: 32px;
  color: #999;
}

.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  color: #666;
}
</style>
